﻿using System;
using System.Linq;
using Super_Management_Mayhem.Content.Spritesheet.Player;
using Super_Management_Mayhem.Control;
using Super_Management_Mayhem.Screens.Playing.ObjectInterfaces;
using Transformable_Engine_v2.Engine.GameObjects.Containers;
using Transformable_Engine_v2.Engine.Graphics;
using Transformable_Engine_v2.Engine.Helper;
using Transformable_Engine_v2.Engine.Input;
using Transformable_Engine_v2.Engine.Transformable_Math.Geometry;

namespace Super_Management_Mayhem.Screens.Playing.Players.Manager
{
    partial class Manager : Container
    {
        private const int TILE_SIZE = 16;
        private readonly TE_Rectangle _boundingBoxWall;
        private readonly TE_Rectangle _boundingBoxCollision;
        private readonly TE_Rectangle _boundingBoxCollect;

        protected readonly Character _character;

        private Direction _currentDirection;

        private PlayerState _currentPlayerState;
        private readonly InputKeys _input;
        private bool _isCarrying;
        protected Direction _latestDirection;

        protected readonly PositionTrackerContainer _player;

        private readonly ImageContainer _shadow;
        protected readonly PlayerContainer _statistics;
        private readonly ImageContainer _tileIndicator;
        private IThrowable _pickUpItem;
        private readonly Container _pickUpItemLayer;

        public enum Direction
        {
            Up,
            Down,
            Left,
            Right,
            None
        }

        public enum Input
        {
            Up,
            Down,
            Left,
            Right,
            Attack,
            Action,
        }

        public enum PlayerState
        {
            Idle,
            Walk,
            PickUp,
            Throw,
            Attack,
            Hurt,
            Action,
            Dead,
            Creation,
            Fall
        }

        public TE_Rectangle BoundingBoxWall
        {
            get
            {
                return _boundingBoxWall + _player.Position;
            }
        }

        public TE_Rectangle BoundingBoxCollision
        {
            get
            {
                return _boundingBoxCollision + _player.Position;
            }
        }

        public TE_Rectangle BoundingBoxCollect
        {
            get
            {
                return _boundingBoxCollect + _player.Position;
            }
        }

        public TE_Vector2 PlayerPosition
        {
            get
            {
                return _player.Position;
            }
        }

        public Manager(TE_Vector2 position,
                       Color skinColor,
                       InputKeys input,
                       PlayerContainer playerContainer,
                       TE_Vector2 previousCameraPosition)
        {

            _isCarrying = false;

            _statistics = playerContainer;
            _currentDirection = Direction.None;
            _latestDirection = Direction.Down;
            _input = input;

            _boundingBoxWall = new TE_Rectangle(-7, -7, 14, 11);
            _boundingBoxCollision = new TE_Rectangle(-7, -14, 14, 18);
            _boundingBoxCollect = new TE_Rectangle(-12, -12, 24, 21);

            _player = new PositionTrackerContainer {
                                                       PositionGridBound = position.Offset(0.5f, 0.5f)
                                                   };
            _tileIndicator = new ImageContainer {
                                                    PositionGridBound = position,
                                                    Sprite = SpriteSheet.GetSprite(SpriteSheetPath, ManagerSheet.Indicator.TileIndicator),
                                                    Color = new Color(skinColor, 100)
                                                };
            AddChildren(_tileIndicator, _player);

            _shadow = new ImageContainer {
                                             Sprite = SpriteSheet.GetSprite(SpriteSheetPath, ManagerSheet.Indicator.ShadowIndicator),
                                             Origin = TE_Rectangle.Alignment.CenterMiddle
                                         };
            _character = new Character(skinColor);

            var dummy = new Character(Color.White)
                            {
                                Visible = false
                            };
            dummy.Die();
            _player.AddChildren(dummy);

            _pickUpItemLayer = new Container();

            _player.AddChildren(_shadow, _character, _pickUpItemLayer);

            KeyboardHandler.OnKeyboardPress += OnKeyPressed;
            KeyboardHandler.OnKeyboardReleased += OnKeyReleased;

            ChangeState(PlayerState.Creation);

            InitializeThrowStateObjects();
            InitializeCollisionObjects();
            InitializeAttackObjects();
            InitializeHurtStateObjects();
            InitializeCamera(previousCameraPosition);
            InitializePickupStateObjects();
        }

        public override void FixedStepUpdate(TimeSpan gameTime)
        {
            if(!IsAlive())
                return;

            UpdateCamera(gameTime);
            switch (_currentPlayerState)
            {
                case PlayerState.Idle:
                    UpdateIdleState(gameTime);
                    break;
                case PlayerState.Walk:
                    UpdateWalkState(gameTime);
                    break;
                case PlayerState.PickUp:
                    UpdatePickupState(gameTime);
                    break;
                case PlayerState.Throw:
                    UpdateThrowState(gameTime);
                    break;
                case PlayerState.Attack:
                    UpdateAttackState(gameTime);
                    break;
                case PlayerState.Hurt:
                    UpdateHurtState(gameTime);
                    break;
                case PlayerState.Action:
                    break;
                case PlayerState.Dead:
                    UpdateDeadState(gameTime);
                    break;
                case PlayerState.Creation:
                    UpdateCreationState(gameTime);
                    break;
                case PlayerState.Fall:
                    UpdateFallState(gameTime);
                    break;
            }

            base.FixedStepUpdate(gameTime);
        }

        public override void Update(TimeSpan gameTime)
        {
            //Update tile indicator position
            _tileIndicator.PositionGridBound = new TE_Vector2((int) (_player.Position.X) / TILE_SIZE,
                                                              (int) (_player.Position.Y) / TILE_SIZE);

            base.Update(gameTime);
        }

        protected void ChangeState(PlayerState _nextState)
        {
            if(_currentPlayerState == PlayerState.Dead)
                return;

            _currentPlayerState = _nextState;
            switch (_nextState)
            {
                case PlayerState.Idle:
                    InitializeIdleState();
                    break;
                case PlayerState.Walk:
                    InitializeWalkState();
                    break;
                case PlayerState.PickUp:
                    InitializePickupState();
                    break;
                case PlayerState.Throw:
                    InitializeThrowState();
                    break;
                case PlayerState.Attack:
                    if(_isCarrying)
                    {
                        ChangeState(PlayerState.Throw);
                    }
                    else
                    {
                        foreach (var item in Playscreen.Map.PickableItems.Where(item => item.IsPickable && CollisionHelper.Intersects(item.GetBoundingBoxPickup(), ItemBoundingBox))) 
                        {
                            ChangeState(PlayerState.PickUp);
                            _pickUpItem = item.Pickup();
                            _pickUpItemLayer.AddChildren((Container) _pickUpItem);
                            return;
                        }
                        InitializeAttackState();
                    }
                    break;
                case PlayerState.Hurt:
                    InitializeHurtState();
                    break;
                case PlayerState.Action:
                    break;
                case PlayerState.Dead:
                    InitializeDeadState();
                    break;
                case PlayerState.Creation:
                    InitializeCreationState();
                    break;
                case PlayerState.Fall:
                    InitializeFallState();
                    break;
            }
        }

        private void HandleKeyPress(Input input)
        {
            switch (_currentPlayerState)
            {
                case PlayerState.Idle:
                    HandleKeyPressIdleState(input);
                    break;
                case PlayerState.Walk:
                    HandleKeyPressWalkState(input);
                    break;
                case PlayerState.PickUp:
                    HandleKeyPressPickupState(input);
                    break;
                case PlayerState.Throw:
                    HandleKeyPressThrowState(input);
                    break;
                case PlayerState.Attack:
                    HandleKeyPressAttackState(input);
                    break;
                case PlayerState.Hurt:
                    HandleKeyPressHurtState(input);
                    break;
                case PlayerState.Action:
                    break;
                case PlayerState.Dead:
                    HandleKeyPressDeadState(input);
                    break;
                case PlayerState.Creation:
                    HandleKeyPressCreationState(input);
                    break;
                case PlayerState.Fall:
                    HandleKeyPressFallState(input);
                    break;
            }
        }

        private void HandleKeyRelease(Input input)
        {
            switch (_currentPlayerState)
            {
                case PlayerState.Idle:
                    HandleKeyReleaseIdleState(input);
                    break;
                case PlayerState.Walk:
                    HandleKeyReleaseWalkState(input);
                    break;
                case PlayerState.PickUp:
                    HandleKeyReleasePickupState(input);
                    break;
                case PlayerState.Throw:
                    HandleKeyReleaseThrowState(input);
                    break;
                case PlayerState.Attack:
                    HandleKeyReleaseAttackState(input);
                    break;
                case PlayerState.Hurt:
                    HandleKeyReleaseHurtState(input);
                    break;
                case PlayerState.Action:
                    break;
                case PlayerState.Dead:
                    HandleKeyReleaseDeadState(input);
                    break;
                case PlayerState.Creation:
                    HandleKeyReleaseCreationState(input);
                    break;
                case PlayerState.Fall:
                    HandleKeyReleaseFallState(input);
                    break;
            }
        }

        private void OnKeyPressed(KeyboardInput input)
        {
            if(!Playscreen.Controller.IsStarted)
                return;

            if (input.KeyCode == _input.UpKey)
            {
                _input.UpKeyState = true;
                HandleKeyPress(Input.Up);
            }
            else if (input.KeyCode == _input.DownKey)
            {
                _input.DownKeyState = true;
                HandleKeyPress(Input.Down);
            }
            else if (input.KeyCode == _input.LeftKey)
            {
                _input.LeftKeyState = true;
                HandleKeyPress(Input.Left);
            }
            else if (input.KeyCode == _input.RightKey)
            {
                _input.RightKeyState = true;
                HandleKeyPress(Input.Right);
            }
            else if (input.KeyCode == _input.ActionKey)
            {
                HandleKeyPress(Input.Action);
            }
            else if (input.KeyCode == _input.AttackKey)
            {
                HandleKeyPress(Input.Attack);
            }
        }

        private void OnKeyReleased(KeyboardInput input)
        {
            if(!Playscreen.Controller.IsStarted)
                return;

            if (input.KeyCode == _input.UpKey)
            {
                _input.UpKeyState = false;
                HandleKeyRelease(Input.Up);
            }
            else if (input.KeyCode == _input.DownKey)
            {
                _input.DownKeyState = false;
                HandleKeyRelease(Input.Down);
            }
            else if (input.KeyCode == _input.LeftKey)
            {
                _input.LeftKeyState = false;
                HandleKeyRelease(Input.Left);
            }
            else if (input.KeyCode == _input.RightKey)
            {
                _input.RightKeyState = false;
                HandleKeyRelease(Input.Right);
            }
            else if (input.KeyCode == _input.ActionKey)
            {
                HandleKeyRelease(Input.Action);
            }
            else if (input.KeyCode == _input.AttackKey)
            {
                HandleKeyRelease(Input.Attack);
            }
        }

        
    }
}
